package com.pandora.framework.http;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;

import com.pandora.common.check.APIContentChecks;
import com.pandora.common.check.RequestChecks;
import com.pandora.common.exception.EduException;
import com.pandora.common.util.CommonUtils;
import com.pandora.common.util.StringUtils;
import com.pandora.common.util.TimeUtils;
import com.pandora.common.util.WebUtils;
import com.pandora.framework.action.IAction;
import com.pandora.framework.constant.Constants;
import com.pandora.framework.constant.ResponseConstants;
import com.pandora.framework.constant.ServiceConstants;
import com.pandora.framework.util.LogUtils;
import com.pandora.framework.util.PropertiesUtils;
import com.pandora.framework.util.ResponseUtils;
import com.pandora.framework.util.ServiceUtils;
import com.pandora.framework.vo.ServiceConfigVO;
import com.pandora.framework.vo.ServiceCoreVO;

/**
 * 接口服务基类
 * 
 * @author JingChenglong 2017/12/18 11:27
 *
 */
public class BaseService {

	protected ServiceCoreVO serviceCoreVO = null;// 封装请求体信息
	private HttpServletRequest request = null;
	private HttpServletResponse response = null;

	/** 请求信息初始化 */
	protected void init(String serviceType) {

		String requestTime = TimeUtils.getSysTime();
		String ip = WebUtils.getIp(request);

		serviceCoreVO = new ServiceCoreVO();
		serviceCoreVO.setRequestTime(requestTime);
		serviceCoreVO.setServiceType(serviceType);
		serviceCoreVO.setIp(ip);
		serviceCoreVO.setRequestUrl(StringUtils.nullToStrTrim(request.getRequestURL().toString()));
		serviceCoreVO.setOperateLogno(StringUtils.getRandom(serviceType + ip + requestTime).toLowerCase());
	}

	protected ModelAndView response(String serviceType, HttpServletRequest request, HttpServletResponse response) {
		this.request = request;
		this.response = response;

		init(serviceType);

		Object object = null;

		try {
			// 校验HTTP请求合法性并提取请求体信息进行封装
			RequestChecks.getInstance(serviceCoreVO, request).checkRequest();

			// 校验请求内容合法性并提取请求和接口信息
			ServiceConfigVO configVO = APIContentChecks.getInstance(serviceCoreVO, request).checkContent();

			// 请求日志记录
			LogUtils.logInfo("serviceCoreVO.getServiceType():" + serviceCoreVO.getServiceType()
					+ ";configVO.getResFlag():" + configVO.getResFlag());

			// 设置响应体
			if (ServiceConstants.SERVICETYPE_HTTP.equalsIgnoreCase(serviceCoreVO.getServiceType())) {
				serviceCoreVO.setResponse(response);
			}

			// 方法执行
			execute(configVO.getClassObject());

			// 结果处理
			object = dealObject(serviceCoreVO.getResObject());
		} catch (EduException e) {
			LogUtils.logError(Thread.currentThread().getName() + "--" + CommonUtils.getTraceInfo() + e.getMessage());
			object = dealException(e.getMessage());
		}

		// 设置HTTP相应码
		setStatus();

		if (object != null
				&& (serviceCoreVO.getResponse() != null || ResponseConstants.SUCCESS != serviceCoreVO.getCode())) {
			ServiceUtils.responseContent(response, getRescontent(object));
		}

		object = null;

		// 接口操作日志
		ServiceUtils.operateLog(serviceCoreVO);
		return null;
	}

	/**
	 * 执行请求方法
	 * 
	 * @param classObject
	 */
	private void execute(Class<?> classObject) throws EduException {

		if (classObject == null) {
			throw new EduException(ResponseConstants.INTERFACE_UNDEFINED);
		}

		IAction iaction = null;

		try {
			iaction = (IAction) classObject.newInstance();
		} catch (Exception e) {
			LogUtils.logError(CommonUtils.getTraceInfo() + e.getMessage());
			throw new EduException(ResponseConstants.INTERFACE_ERROR);
		}

		ServiceCoreVO result = iaction.execute(serviceCoreVO);
		if (result == null) {
			throw new EduException(ResponseConstants.INTERFACE_RESULT_ERROR);
		}

		serviceCoreVO = result;
	}

	/**
	 * 处理相应结果
	 * 
	 * @param resObject
	 * @return
	 */
	private Object dealObject(Object resObject) {

		if (resObject == null) {
			serviceCoreVO.setCode(ResponseConstants.SYSTEMBUSY);
			return ResponseConstants.SYSTEMBUSY;
		}

		String code = "";
		if (resObject instanceof Integer) {
			code = resObject.toString();
		} else if (resObject instanceof String) {
			code = resObject.toString();
		}

		if (StringUtils.isNotEmpty(code)) {

			if (ServiceUtils.isInfoCode(code)) {
				serviceCoreVO.setCode(StringUtils.nullToIntZero(code));
			} else {
				serviceCoreVO.setCode(ResponseConstants.SYSTEMBUSY);
				serviceCoreVO.setException(serviceCoreVO.getException() + ";" + code);
			}

			return serviceCoreVO.getCode();
		}

		return resObject;
	}

	/**
	 * 处理异常
	 * 
	 * @param msg
	 * @return
	 */
	private Object dealException(String msg) {

		String error = "";

		msg = StringUtils.nullToStrTrim(msg);

		if (ServiceUtils.isInfoCode(msg)) {
			serviceCoreVO.setCode(StringUtils.nullToIntZero(msg));
			if (ResponseConstants.SUCCESS != StringUtils.nullToIntZero(msg)) {
				error = PropertiesUtils.getCommonMessage(msg);
				if (StringUtils.isEmpty(error) || Constants.UNKNOWN.equalsIgnoreCase(error)) {
					error = PropertiesUtils.getBusinessMessage(msg);
				}
			}
		} else {
			serviceCoreVO.setCode(ResponseConstants.SYSTEMBUSY);
			error = msg;
		}

		if (StringUtils.isNotEmpty(error)) {
			serviceCoreVO.setException(error);
		}

		return msg;
	}

	/**
	 * 获取响应内容
	 * 
	 * @param object
	 * @return
	 */
	public String getRescontent(Object object) {

		String resContent = ResponseUtils.getInstance(serviceCoreVO.getFormat(), serviceCoreVO.getOperateLogno())
				.response(object);

		if (StringUtils.isEmpty(resContent)) {
			serviceCoreVO.setCode(ResponseConstants.SYSTEMBUSY);
			// TODO 错误时输出响应内容
		}

		serviceCoreVO.setReslength(StringUtils.getRealLength(resContent));
		serviceCoreVO.setResContent(resContent);
		return resContent;
	}

	/** 设置请求HTTP相应码 */
	private void setStatus() {

		int code = serviceCoreVO.getCode();
		int status = 200;

		switch (code) {
		case ResponseConstants.SUCCESS:
			status = 200;
			break;
		case ResponseConstants.SERVICE_INTERFACE_NULL:
			status = 404;
			break;
		case ResponseConstants.REQUEST_METHOD_NOSUPPORT:
			status = 405;
			break;
		case ResponseConstants.REQUEST_ENTITY_TOOLARGE:
			status = 413;
			break;
		case ResponseConstants.SYSTEMBUSY:
			status = 500;
			break;
		default:
			status = 403;
			break;
		}

		response.setStatus(status);
	}
}